package org.sean.framework.canary.loadbalancer.predicate;

import org.sean.framework.canary.core.CanaryHeader;
import org.sean.framework.canary.core.CanaryProperties;
import org.sean.framework.canary.core.CanaryUtils;
import org.sean.framework.canary.loadbalancer.CanaryPredicate;
import org.sean.framework.canary.loadbalancer.PredicateKey;
import org.sean.framework.context.ApplicationInfo;
import org.sean.framework.logging.Logger;
import org.sean.framework.util.ObjectUtil;
import org.sean.framework.util.StringUtil;
import org.sean.framework.web.filter.HeaderFilter;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.http.HttpHeaders;

import java.util.ArrayList;
import java.util.List;

/**
 * Label 匹配规则
 *
 * @author xielei
 */
public class LabelPredicate extends CanaryPredicate {
    // 灰度规则顺序
    private int level = 1;

    public LabelPredicate(int level) {
        this.level = level;
    }

    /**
     * 选择器
     *
     * @param server  服务实例
     * @param headers headers
     * @return 是否选中
     */
    @Override
    public boolean getSelector(ServiceInstance server, HttpHeaders headers) {
        // 开发中过滤本网段不可访问的服务
        if (!ApplicationInfo.isReleased() && !CanaryUtils.canChoose(server.getHost())) {
            return false;
        }

        String serverName = server.getServiceId();
        StringBuilder log = new StringBuilder();
        log.append(StringUtil.formatContent("[{0}] : {1}", serverName, server.getUri()));

        CanaryHeader header = new CanaryHeader();
        header.setDeviceId(headers.getFirst(HeaderFilter.HEADER_DEVICE_ID));
        header.setTargetIp(headers.getFirst(HeaderFilter.HEADER_TARGET_IP));
        header.setClientId(headers.getFirst(HeaderFilter.HEADER_CLIENT_ID));
        header.setTargetId(headers.getFirst(HeaderFilter.HEADER_TARGET_ID));

        List<String> ruleLabels = new ArrayList<>();
        CanaryProperties.Canary canaryRule = null;
        // TargetIp
        if (StringUtil.isNotEmpty(header.getTargetIp())) {
            canaryRule = CanaryUtils.getLabelByTargetIp(header.getTargetIp());
        }
        // ClientId
        if (StringUtil.isNotEmpty(header.getClientId())) {
            CanaryProperties.Canary r = CanaryUtils.getLabelByClientId(header.getClientId());
            canaryRule = r == null ? canaryRule : r;
        }
        // DeviceId
        if (StringUtil.isNotEmpty(header.getDeviceId())) {
            CanaryProperties.Canary r = CanaryUtils.getLabelByDeviceId(header.getDeviceId());
            canaryRule = r == null ? canaryRule : r;
        }
        // TargetId
        if (StringUtil.isNotEmpty(header.getTargetId())) {
            CanaryProperties.Canary r = CanaryUtils.getLabelByTargetId(header.getTargetId());
            canaryRule = r == null ? canaryRule : r;
        }
        if (canaryRule != null) {
            if (ObjectUtil.isNotEmpty(canaryRule.getLabels())) {
                ruleLabels.addAll(canaryRule.getLabels());
            }
        }

        String serverLabel = CanaryUtils.getServerLabel(server);
        boolean result = false;
        if (ruleLabels.size() >= level) {
            result = ruleLabels.get(level - 1).equalsIgnoreCase(serverLabel);
        }
        log.append(StringUtil.formatContent(" - label : [{0}]", serverLabel));
        log.append(StringUtil.formatContent(" -- rule label : [{0}]", ruleLabels));
        log.append(StringUtil.formatContent(" -- match result : [{0}]", result));
        logger.debug(log.toString());
        return result;
    }

}
